/*-------------------------------------------------------------------------

***************** Modification History ***********************************
   @doc
   @module Fields.c - Transaction Flow functions |
   @end

$Log: /SoftPay/SPK2SIM/Source/Tran/fields.c $
**************************************************************************

   Copyright (C) 1999 by VeriFone, Inc.

   All rights reserved.  No part of this software may be reproduced,
   transmitted, transcribed, stored in a retrieval system, or translated
   into any language or computer language, in any form or by any means,
   electronic, mechanical, magnetic, optical, chemical, manual or otherwise,
   without the prior written permission of VeriFone, Inc.

---------------------------------------------------------------------------*/
#define VSFIELDS_C

#include <project.h>

// #include <beetle.h>
//#include <beetleplug.h>

#include <stdlib.h>
#include <applidl.h>
#include <aclconio.h>
#include <acldev.h>
#include <aclstr.h>
#include <dbmgr.h>
#include <string.h>
#include <power.h>

/** /#define DEBUG_VSFIELDS*/
#ifdef DEBUG_VSFIELDS
#define DEBUG_95
#endif

#include <define.h>
#include <transact.h>
#include <fields.h>
#include <card.h>
#include <cst.h>
#include <bdt.h>
#include <cdt.h>
#include <dct.h>
#include <hdt.h>
#include <tblutil.h>
#include <tct.h>
#include <pct.h>
#include <iit.h>
#include <mht.h>
#include <msg.h>
#include <msgfuncs.h>
#include <modemmsg.h>
#include <modem.h>
#include <tran.h>
#include <date.h>
#include <ui.h>
#include <entry.h>
#include <oper.h>
#include <pscalls.h>
#include <trt.h>
#include <print.h>
#include <pbatch.h>
#include <pcheck.h>
#include <spdebug.h>
#include <review.h>
#include <ict.h>
#include <logo.h>
#include <amount.h>
#include <format.h>
#include <tip.h>
#include <confio.h>
#include <multilng.h>
#include <gds.h>
#include <codesec.h>
#include <operate.h>
#include <tmadef.h>

#define SUPER_PW                1
#define MAN_PW                  2
#define BOTH_PW                 (SUPER_PW + MAN_PW)
#define PRT_ORIGINAL       1

extern char szTempMsg[MESSAGE_SIZE + 1];

/* Local Defines */
#define ACT_GROUP_ID_IDX    0
#define HDT_GROUP_ID_IDX    0

/*********************************************************************************************
* @func int | inComputeAndDispTotal |
*
*       adds all the transaction amounts and displays it on the screen.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inComputeAndDispTotal(TRANSACTION_OBJECT* pobTran) {
    char szAmount[AMT_SIZE + 1];
    unsigned long ulTimerCount;
    int inLine = (obDisp.inInputLine - 1);

    /**/pdebug(("--inComputeAndDispTotal--"));/**/

    inLine = (obDisp.inInputLine - 1);

    vdComputeTransactionTotal(szAmount, pobTran);

    pobTran->srBKey.lnTotalOfTransactionAmount = atol(szAmount);

    if (fGetOffline(pobTran) && !pobTran->srBRec.fCloseTabSameCard)
        pobTran->srBRec.lnOrigTotalTransactionAmount = 0L;

    if (!fGetOffline(pobTran))
        pobTran->srBRec.lnOrigTotalTransactionAmount = atol(szAmount);

    pobTran->srBRec.fComputeOverage = fComputeOverage(pobTran);

    sprintf(szAmount, SUBSTITUTE_LD, pobTran->srBKey.lnTotalOfTransactionAmount);

    /*
     *      Display Total Amount
     */
    vdFormatAmount(szAmount, VS_TRUE); {
        int inDispRow = obDisp.inInputLine;
        int inRowLim = inGetRowLim();
        int inDispCol,
        inDummyCol = 1;

        vdScrollDataEntry(!obDisp.blNoScrollEntries);
        vdDispMsgAt(TOTALAMT_MSG9, obDisp.inHomeCol, inDispRow, CLR_EOL);
        if (obDisp.blActionFontASC8x21)
            vdDispStrAtRight(szAmount, inDispRow, CLR_EOL);
        else {
            /*
               *        Display Amount Right Justified in English 8x21 font
               */
            inDispCol = ((21 - strlen(szAmount)) + 1);
            vdCalculateCoord(GRID_4x8_TO_8x21, &inDummyCol, &inDispRow);
            vdDisplayAt_ASC8X21(inDispCol, inDispRow, szAmount, NO_CLEAR);
        }
    }

    /*
     *      Delay so that total amount may be seen on the limited display capabilities terminals
     *      or during OFFLINE Transactions.
     */
    if (fGetOffline(pobTran)) {
        int inPause;

        inPause = (int) (1.25 * A_SECOND);
        ulTimerCount = set_itimeout(NO_CLOCK_HANDLE(unsigned)inPause, (long) TM_TICKS);
        while (!KBHIT() && CHECK_TIMEOUT(ulTimerCount)) ;
    }

    return(VS_SUCCESS);
}
/*********************************************************************************************
* @func int | getnewamt |
*
*       pulls new information about additional indexes by account number
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int getnewamt(TRANSACTION_OBJECT* pobTran) {
    char szCardLabel[CLABEL_SIZE + 1];
    char szDisplayBuffer[DISP_STR_LEN + 1];
    char szAmt[AMT_SIZE + 1];
    long lnBaseAmt = 0L;
    int inAmtLine = obDisp.inDetailLine;
    int inRowLim = inGetRowLim();
    int inOff = 1;

    lnBaseAmt = (pobTran->srBKey.lnTotalOfTransactionAmount - pobTran->srBRec.lnTaxAmount - pobTran->srBRec.lnTipAmount);

    if (lnBaseAmt > 0L) {
        if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
            inAmtLine = (obDisp.inFirstLineCOne - 1);
            vdGetMessageFromFile(O3200_OLD_AMOUNT_MSG, szDisplayBuffer);
            inRowLim = obDisp.in3200BarCol - 1; /* force it, due to situation */
        }
        sprintf(szAmt, SUBSTITUTE_LD, lnBaseAmt);
        vdFormatAmount(szAmt, VS_FALSE);
        vdTrimLeadSpaces(szAmt);
        pad(szAmt, szAmt, ' ', AMT_STR_SIZE, RIGHT);
        vdDisplayAt(obDisp.inHomeCol, inAmtLine, szDisplayBuffer, CLR_LINE);

        vdDisplayAt(inRowLim - AMT_STR_SIZE + inOff, inAmtLine, szAmt, NO_CLEAR);

        if (pobTran->srBRec.inTranCardType == DEBIT_CARD)
            vdGetMessageFromFile(DEBIT_MSG, szCardLabel);
        else
            strcpy(szCardLabel, szGetCardLabel());
        vdDisplayAt(obDisp.inHomeCol, obDisp.inTitleLine + 1, szCardLabel, CLR_EOL);
    }
    vdSGCode(PRE_COMP);
    return(VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inLoadDefaultCurrency |
*
*       Load the default currency for the host selected.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inLoadDefaultCurrency(TRANSACTION_OBJECT* pobTran) {
    if (inLoadCSTRec(inGetCurrencyIdx()) != VS_SUCCESS) {
        vdSGErrorMessage(CST_ERR_MSG);
        return(VS_ERR);
    }
    if (inLoadBDTRec(inGetBatchIndex()) != VS_SUCCESS) {
        vdSGErrorMessage(BDT_ERR_MSG);
        return(VS_ERR);
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inLoadDefaultHost |
*
*       Load the default host for the card selected.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inLoadDefaultHost(int inHostIndex) {
    short shCommLink;
    TRANSACTION_OBJECT* pobTran;

    pobTran = pstGet_pobTran();
    if (pobTran == NULL)
        return VS_ERR;
LOG_PRINTFF((0x08L, "inLoadDefaultHost 2A "));
    if (inLoadHostData(inHostIndex) != VS_SUCCESS)
        return(VS_ERR);
LOG_PRINTFF((0x08L, "inLoadDefaultHost 2 B"));
    if (inLoadDCTRec(inHostIndex) != VS_SUCCESS) {
        vdSGErrorMessage(DCT_ERR_MSG);
        return(VS_ERR);
    }
LOG_PRINTFF((0x08L, "inLoadDefaultHost 2 C"));
    /*
     *      Initialize COMM Object based on HDT Link Type variable.
     */
     LOG_PRINTFF((0x08L, "inLoadDefaultHost 2D "));
    if (inGGOpCode() == SETTLE_OPERATION)
        shCommLink = shGetSettleCommLinkType();
    else
        shCommLink = shGetCommLinkType();
LOG_PRINTFF((0x08L, "inLoadDefaultHost 2 E  %d",shCommLink));

    if (inInitializeComm(shCommLink) != VS_SUCCESS) {
        vdSGErrorMessage(COMM_INIT_ERR_MSG);
        return(VS_ERR);
    }
	LOG_PRINTFF((0x08L, "inLoadDefaultHost 2 "));

    return (VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inSelectAndLoadHost |
*
*       If Card entered points to more than one host, it asks the
*                  user to select one and it loads the right global
*                  variables.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inSelectAndLoadHost(TRANSACTION_OBJECT* pobTran) {
    short shGroupId ;
    int inHostIndex;
    short shCommLink;


    shGroupId = (short) inGetHostGroupID();

    if ((inHostIndex = inSelectHost(HDT_GROUP_ID_IDX, (char *) &shGroupId, inCredDebBatchExists, BATCH_EMPTY_MSG)) >= 0) {

	if (inLoadHostData(inHostIndex) != VS_SUCCESS)
            return(VS_ERR);
    } else if (inHostIndex == VS_ESCAPE)
        return(VS_ESCAPE);
    else {
        pdebug(("inHostIndex=%d", inHostIndex));
        vdSGErrorMessage(HOST_SELECTION_ERR_MSG21);
        return(VS_ERR);
    }

    vdSetHostHandle(inHostIndex);


    if (inLoadDCTRec(inHostIndex) != VS_SUCCESS) {
        vdSGErrorMessage(DCT_ERR_MSG);
        return(VS_ERR);
    }

    /*
     *  Must load ACT before opening batch
     */
    if (inLoadDefaultCurrency(pobTran) != VS_SUCCESS)
        return (VS_ERR);

    /*
     *      Initialize COMM Object based on HDT Link Type variable.
     */
    if (inGGOpCode() == SETTLE_OPERATION)
        shCommLink = shGetSettleCommLinkType();
    else
        shCommLink = shGetCommLinkType();

    if (inInitializeComm(shCommLink) != VS_SUCCESS) {
        vdSGErrorMessage(COMM_INIT_ERR_MSG);
        return(VS_ERR);
    }


    return (VS_SUCCESS);
}


/*********************************************************************************************
* @func int | inAVS |
*
*       This function prompts user for zip code and/or address.
*                  The function applies to manual card entry only
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inAVS(TRANSACTION_OBJECT* pobTran) {
    int inResult;
    char szGetZipCode[ZIPCODE_SIZE + 1];
    char szGetAddress[ADDRESS_SIZE + 1];
    int inAVSMode;

    int inRowLim = inGetRowLim();

    inAVSMode = inGetAVS();

    if ((inAVSMode != NO_AVS) && (pobTran->srBRec.fManual == VS_TRUE)) {
        vdSetNextLineEntry();   /* for 3200 */
        if (obDisp.inTerminalType == TERMINAL_OMNI_3200)
            obDisp.blNextLineCleanup = VS_TRUE; /* needed */
        if (inAVSMode == AVS_ADDRESS || inAVSMode == AVS_BOTH) {
            inResult = inEnterWithMessage(AVS_ADDRESS_MSG, SCROLL_DISPLAY_TRUE, szGetAddress, INPUT_ALNUMS, ADDRESS_SIZE, NULL_PFI);

            window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, obDisp.inCharsPerColumn);
            if (inResult < 0) {
                vdSGErrorMessage(TXN_CANCELLED);
                return (VS_ESCAPE);
            }
            strcpy(pobTran->szAddress, szGetAddress);
        }
        vdClrNextLineEntry();   /* for 3200 */
        if (inAVSMode == AVS_ZIPCODE || inAVSMode == AVS_BOTH) {
            inResult = inEnterWithMessage(AVS_ZIPCODE_MSG, SCROLL_DISPLAY_TRUE, szGetZipCode, INPUT_NUMS, 9, inZipCodeValidator);

            window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, obDisp.inCharsPerColumn);
            if (inResult < 0) {
                vdSGErrorMessage(TXN_CANCELLED);
                return (VS_ESCAPE);
            }
            strcpy(pobTran->szZipCode, szGetZipCode);
        }
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inCheckSettleFlag |
*
*       Check the HDT MustSettleFlag to determine if terminal
*                  must settle before performing the Operation.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inCheckSettleFlag(TRANSACTION_OBJECT* pobTran) {
    char szMessage[MESSAGE_SIZE + 1];
    char szHostName[HOST_NAME_SIZE + 1];
    unsigned char ucLocalHDTRec[SIZE_HDT_REC + 1];
    //HDT_REC srLocalHDTRec;

    if (fGetMustSettleFlag()) {
#ifdef TMA_DEFINED
        vdIncMICounter(MI_NO_MUST_SETTLES);
#endif  /* TMA_DEFINED */
        /* Append Host Specific Name to Must Settle Message */
        vdGetMessageFromFile(MUST_SETTLE_ERR_MSG, szMessage);

        if (!fGetIndependentBatch()) {
            if (inLoadHDTRecFromStruct(inGetBatchIndex(), ucLocalHDTRec) != VS_SUCCESS) {
                vdDisplayMessageFromFile(HDT_ERR_MSG21, ERROR_MSG);
                return(VS_ERR);
            }
            strlcpy(szHostName, szGetHostNameFromStruct(ucLocalHDTRec), HOST_NAME_SIZE);
        } else
            strlcpy(szHostName, szGetHostName(), HOST_NAME_SIZE);

        vdClearNonTitleLines();
        if ((get_font_mode() == 2) && (getgrid() == 0)) {
            vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szMessage, CLR_EOL);
            inMLDisplayAt(strlen(szMessage) + 1, obDisp.inStatusLine, szHostName, CLR_EOL, ML_USE_GIVEN_FONT, ML_MENU_FONT, ASC4X16_VFT);
            vdBeep();
            vdFlushKeyboardBuffer();
            inWaitKey(inGetIdleTimeOut());
        } else {
            strcat(szMessage, szHostName);
            vdDisplayErrorString(szMessage);
        }
        return(VS_ERR);
    } else
        return(VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inChkMustSettleFlag |
*
*       Check the HDT MustSettleFlag to determine if terminal
*                  must settle before performing the transaction
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inChkMustSettleFlag(TRANSACTION_OBJECT* pobTran) {
    char szMessage[MESSAGE_SIZE + 1];
    char szHostName[HOST_NAME_SIZE + 1];
    unsigned char ucLocalHDTRec[SIZE_HDT_REC + 1];
    //HDT_REC srLocalHDTRec;

    if (fGetMustSettleFlag()) {
#ifdef TMA_DEFINED
        vdIncMICounter(MI_NO_MUST_SETTLES);
#endif  /* TMA_DEFINED */
        /* Append Host Specific Name to Must Settle Message */
        vdGetMessageFromFile(MUST_SETTLE_ERR_MSG, szMessage);

        if (!fGetIndependentBatch()) {
            if (inLoadHDTRecFromStruct(inGetBatchIndex(), ucLocalHDTRec) != VS_SUCCESS) {
                vdDisplayMessageFromFile(HDT_ERR_MSG21, ERROR_MSG);
                return(VS_ERR);
            }
            strlcpy(szHostName, szGetHostNameFromStruct(ucLocalHDTRec), HOST_NAME_SIZE);
        } else
            strlcpy(szHostName, szGetHostName(), HOST_NAME_SIZE);

        vdClearNonTitleLines();

        if ((get_font_mode() == 2) && (getgrid() == 0)) {
            vdDisplayAt(obDisp.inHomeCol, obDisp.inStatusLine, szMessage, CLR_EOL);
            inMLDisplayAt(strlen(szMessage) + 1, obDisp.inStatusLine, szHostName, CLR_EOL, ML_USE_GIVEN_FONT, ML_MENU_FONT, ASC4X16_VFT);
            vdBeep();
            vdFlushKeyboardBuffer();
            inWaitKey(inGetIdleTimeOut());
        } else {
            strcat(szMessage, szHostName);
            vdDisplayErrorString(szMessage);
        }
        return(VS_ERR);
    } else
        return(VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inCreditPredial |
*
*       This implements pre-dialing functionality
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inCreditPredial(TRANSACTION_OBJECT* pobTran) {
    int inRetVal = VS_SUCCESS,
    inResult;

    /**/pdebug(("--inCreditPredial--"));/**/

    /*
     *      This flow item applies to non-DEBIT/EBT Transactions only
     */
    //if (pobTran->srBRec.inTranCardType != DEBIT_CARD && pobTran->srBRec.inTranCardType != EBT_CARD && pobTran->inChipStatus != EMV_CARD) {
   //jrd request for EMV predial
    if (pobTran->srBRec.inTranCardType != DEBIT_CARD && pobTran->srBRec.inTranCardType != EBT_CARD) {
        /*
         *      Not a  DEMO Transaction
         */

        if (fGetDemoMode() != VS_TRUE) {
            /*
             *      Not an Offline
             */

            if (!fGetOffline(pobTran) ) {
                /*
                 *      Host Predial flag is set
                 */

                if (fGetCreditPredial()) {
                    /*
                     *      Debits are always online,
                     *      do not dial if Fast Payment flag is enabled
                     */

                    if (inGetFPSType() == FPS_NO) {

                        if (obCommunication.inBegin) {
                            /*
                             *      Was returning VS_ERR all the time,
                             *      causing junk to be printed in cases
                             *      like NO_LINE etc
                             */
                            /**/pdebug(("BeginDial"));/**/

                            if ((inResult = obCommunication.inBegin(&obCommunication, shGetCommunicationIndex(), VS_TRUE)) != VS_SUCCESS) {

				    inRetVal = inResult;
                                if (lnGGErrorMessage() == 0)
                                    vdSGErrorMessage(PREDIAL_ERROR_MSG21);
                            }
                            pobTran->fPredialed = VS_TRUE;
                        }
                    }
                }
            }
        }
    }

    /**/pdebug(("inRetVal=%d", inRetVal));/**/
    return (inRetVal);
} /* End of inCreditPredial () */

/*********************************************************************************************
* @func int | inDebitPredial |
*
*       This implements pre-dialing functionality for DEBIT
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/
#ifndef REMOVE_CORE_DEBIT_PREDIAL
int inDebitPredial(TRANSACTION_OBJECT* pobTran) {
    int inRetVal = VS_SUCCESS,
    inResult;

    /**/pdebug(("--inDebitPredial--"));/**/

    /*
     *      This flow item applies to DEBIT/EBT Transactions only
     */
    if (pobTran->srBRec.inTranCardType == DEBIT_CARD || pobTran->srBRec.inTranCardType == EBT_CARD) {
        /*
         *      Not a  DEMO Transaction
         */
        if (fGetDemoMode() != VS_TRUE) {
            /*
             *      Not an Offline
             */
            if (!fGetOffline(pobTran)) {
                /*
                 *      Check Debit Predial flag before predialing
                 */
                if (fGetDebitPredial()) {
                    if (obCommunication.inBegin) {
                        /*
                         *      Was returning VS_ERR all the time,
                         *      causing junk to be printed in cases
                         *      like NO_LINE etc
                         */
                        /**/pdebug(("BeginDial"));/**/
                        if ((inResult = obCommunication.inBegin(&obCommunication, shGetCommunicationIndex(), VS_TRUE)) != VS_SUCCESS)
                            inRetVal = inResult;
                        pobTran->fPredialed = VS_TRUE;
                    }
                }
            }
        }
    }

    /**/pdebug(("inRetVal=%d", inRetVal));/**/
    return (inRetVal);
} /* End of inDebitPredial () */
#endif /* #ifndef REMOVE_CORE_DEBIT_PREDIAL */


/*********************************************************************************************
* @func int | inDupCheck |
*
*       This functions performs a Duplicate transaction check based
*                  on the Acct #, Amount, and Transaction Type.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/
#ifndef REMOVE_CORE_DUPLICATE_CHECK
int inDupCheck(TRANSACTION_OBJECT* pobTran) {
    signed int     inReturnValue = VS_SUCCESS,
    hFileHandle;
    int inIssuer;
    long lnDbWhat;
    VS_BOOL fDupCheck = VS_FALSE;
    DUPCHK srDUPCHK;
    long lnRecNum,
    lnRetVal;
    char pchBFName[FILENAME_SIZE + 1];
    BATCH_KEY* psrLocalBKey;
    BATCH_REC* psrLocalBRec;
    char* chNull = 0;

    /**/pdebug(("--inDupCheck-%d-", srTCTRec.inDupCheck));/**/
    inIssuer = inGetIssuerNum();

    /*
     *      For online transactions only
     */
    if (!fGetOffline(pobTran)) {
        /*
         *      Perform last data entry Duplicate validation.
         */
        if (inGetDupCheck() > 0) {
            /*
             *      Read last data entry from file
             */
            vdGetDupChkFName(pchBFName);
            if ((hFileHandle = open(pchBFName, O_RDWR)) > 0) {
                int inRead;
                if ((inRead = read(hFileHandle, (char *) &srDUPCHK, sizeof(DUPCHK))) == sizeof(DUPCHK)) {
                    /** /
                    pdebug (("PAN %s <> %s",srDUPCHK.szPAN,pobTran->srBRec.szPAN));
                    pdebug (("AMT %ld <> %ld",srDUPCHK.lnTotalOfTransactionAmount,pobTran->srBKey.lnTotalOfTransactionAmount));
                    pdebug (("CODE %d <> %d",srDUPCHK.inCode,pobTran->srBRec.inCode));
                    */
                    if (memcmp(srDUPCHK.szPAN, pobTran->srBRec.szPAN, sizeof(pobTran->srBRec.szPAN)) == 0 && srDUPCHK.lnTotalOfTransactionAmount == pobTran->srBKey.lnTotalOfTransactionAmount && srDUPCHK.inCode == pobTran->srBRec.inCode)
                        fDupCheck = VS_TRUE;
                }
                close(hFileHandle);
            }
        }

#ifdef BATCH_DEFINED
        /*
         *      Search batch for Duplicate transaction in the batch
         */
        if (inGetDupCheck() > 1 && !fDupCheck) {
            if (inGetLocalBatchStructures(&psrLocalBKey, &psrLocalBRec) != VS_SUCCESS)
                return VS_ERR;
            pobTran->srBSKey.inKeyIdx = KEY_ACC_NUM + KEY_AMT;
            pobTran->srBSKey.BKey.lnLast4 = pobTran->srBKey.lnLast4;
            pobTran->srBSKey.BKey.lnTotalOfTransactionAmount = pobTran->srBKey.lnTotalOfTransactionAmount;
            lnDbWhat = DB_FIRST;
            while ((lnRetVal = lnBatchGetKey(&pobTran->dbBatch, psrLocalBKey, &pobTran->srBSKey, lnDbWhat, psrLocalBRec, &lnRecNum)) == 1L) {
                /*
                 *      Compare full account number and Transaction Code
                 */
                /** /
                pdebug (("PAN %s <> %s",srBRec.szPAN,pobTran->srBRec.szPAN));
                pdebug (("CODE %d <> %d",srBRec.inCode,pobTran->srBRec.inCode));
                */
                if (memcmp(psrLocalBRec->szPAN, pobTran->srBRec.szPAN, sizeof(pobTran->srBRec.szPAN)) == 0 && psrLocalBRec->inCode == pobTran->srBRec.inCode && (psrLocalBRec->inNumberOfAdjusts + psrLocalBRec->inNumberOfTipAdjusts) == 0) {
                    fDupCheck = VS_TRUE;
                    break;
                }
                lnDbWhat = DB_NEXT;
            }
            vdFreeLocalBatchStructures(psrLocalBKey, psrLocalBRec);
        }
#endif // BATCH_DEFINED

        /*
         *      Possible Duplicate Transaction Identified, check with user...
         */
        if (fDupCheck) {
            if ((inReturnValue = obDisp.inDO_ChooseOne(chNull, (char *) pchGetMsg(SEND_DUPLICATE_MSG15), (char *) pchGetMsg(YESNO_MSG5x), 2, NULL_PFI)) == KEY_YES) {
                pobTran->fSendDuplicate = VS_TRUE;
                inReturnValue = VS_SUCCESS;
            } else if (inReturnValue == KEY_NO)
                inReturnValue = VS_ERR;
        }
    }

    /** /pdebug (("Dup Check Done!"));*/
    return (inReturnValue);
} /* End of inDupCheck () */
#endif /* #ifndef REMOVE_CORE_DUPLICATE_CHECK    */

/*********************************************************************************************
* @func int | inSavDupCheck |
*
*       This function saves the account #, amount and Transaction Type
*                  data to a file for use during duplicate checking.
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inSavDupCheck(TRANSACTION_OBJECT* pobTran) {
    int     inReturnValue = VS_ERR,
    hFileHandle;
    DUPCHK srDUPCHK;
    char pchBFName[FILENAME_SIZE + 1];

    /**/pdebug(("--inSavDupCheck--"));/**/
    /*
     *      Load fields to be saved.
     */
    memcpy(srDUPCHK.szPAN, pobTran->srBRec.szPAN, sizeof(pobTran->srBRec.szPAN));
    srDUPCHK.lnTotalOfTransactionAmount = pobTran->srBKey.lnTotalOfTransactionAmount;
    srDUPCHK.inCode = pobTran->srBRec.inCode;
    /*
     *      Save to file
     */
    vdGetDupChkFName(pchBFName);

    if ((hFileHandle = open(pchBFName, O_CREAT | O_TRUNC | O_RDWR)) > 0) {
        if (write(hFileHandle, (char *) &srDUPCHK, sizeof(DUPCHK)) == sizeof(DUPCHK))
            inReturnValue = VS_SUCCESS;
        close(hFileHandle);
    }

    return (inReturnValue);
} /* End of inSavDupCheck () */

/*********************************************************************************************
* @func int | inDisplayResponse |
*
*       Displays the response message saved in the transaction object
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inDisplayResponse(TRANSACTION_OBJECT* pobTran) {
    char szDispMsg[RESP_MSG_SIZE];
    int inChar;

    if (fGetDemoMode()) /* Demo mode response message is handled in demo function */
        return (VS_SUCCESS);



    vdGGRespMsg(szDispMsg); // Since we are printing whatever the host returns; has to be ASCII

    // Now display the approval code [APPROVED] nnnnnnn
    vdDisplayStatusString(szDispMsg);

    /* if transaction meets Fast Payment requirements and the Print Option is NONE,
        wait for key press or idle time out */
    if ((fFPSQualified(pobTran)) && (pobTran->srBRec.inPrintOption == PRT_NONE))
        (void) inWaitKey(inGetIdleTimeOut());

    if (inGetPrinterType() == NOPRINTER || !fGetEnablePrinter() || !fGetPrintReceipt(pobTran)) {
        vdFlushKeyboardBuffer();
        while (((inChar = get_char()) != KEY_CR) && inChar != KEY_CANCEL)
            vdBeep();
    }



    return (VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inScrollOff |
*
*       turns off 3200 scrolling of prompts and amounts
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inScrollOff(TRANSACTION_OBJECT* pobTran) {
    obDisp.blNoScrollEntries = VS_TRUE;
    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inScrollOn |
*
*       turns on 3200 scrolling of prompts and amounts
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inScrollOn(TRANSACTION_OBJECT* pobTran) {
    obDisp.blNoScrollEntries = VS_FALSE;
    return (VS_SUCCESS);
}
/*********************************************************************************************
* @func int | inScrollNextLineOn |
*
*       turns on next line cleanup
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inScrollNextLineOn(TRANSACTION_OBJECT* pobTran) {
    if (getgrid() != 0)
        obDisp.blEntryNextLine = VS_TRUE;
    return (VS_SUCCESS);
}

int FIELDS_CODE_CHECK(char* a,char* b,short* c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);

    return 1;
}

int inLoadHostFromName(TRANSACTION_OBJECT* pobTran,char* pszMyHostName) {
    char szHostName[HOST_NAME_SIZE + 1];
    int inHostNum;
    short shCommLink;

    for (inHostNum = 0; inHostNum < MAX_HOSTS; ++inHostNum) {
        inLoadHDTRec(inHostNum);

        strcpy(szHostName, szGetHostName());
        if (strncmp(szHostName, pszMyHostName, HOST_NAME_SIZE) == 0) {
            /* -- get MHT/CST stuff -- */
            vdSetHostHandle(inHostNum);
            inLoadMHTRec(inGetBatchIndex());
            if (inLoadDefaultCurrency(pobTran) != VS_SUCCESS)
                return(VS_ERR);

            if (inGGOpCode() == SETTLE_OPERATION)
                shCommLink = shGetSettleCommLinkType();
            else
                shCommLink = shGetCommLinkType();

            if (inInitializeComm(shCommLink) != VS_SUCCESS) {
                vdSGErrorMessage(COMM_INIT_ERR_MSG);
                return(VS_ERR);
            }
            return (VS_SUCCESS);
        }
    }

    return(VS_ERR);
}

/*********************************************************************************************
* @func int | inValidateDockingStatus |
*
*       Validate dock status for transactions requiring LANDLINE Modem
*
* @parm TRANSACTION_OBJECT * |pobTran |
*       Transaction object.
*
* @rdesc Returns the success or failure.
* @flag int | VS_SUCCESS
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inValidateDockStatus(TRANSACTION_OBJECT* pobTran) {
    int inRetVal = VS_SUCCESS;
    short shCommLink;

    if (inGGOpCode() == SETTLE_OPERATION)
        shCommLink = shGetSettleCommLinkType();
    else
        shCommLink = shGetCommLinkType();

    if (shCommLink == MODEM_COMM) {
        if (srGDS.fLandLine) {
            if (srGDS.fHandHeld)
                while (get_dock_status() == HANDHELD_UNDOCKED && inRetVal == VS_SUCCESS) {
                    vdDisplayWarningMsg(MUST_DOCK_TERMINAL_MSG21);
                    if (act_kbd_pending_test(KEY_CANCEL)) {
                        vdSetTranError(TXN_CANCELLED);
                        inRetVal = VS_ERR;
                    }
                }
        } else {
            vdDisplayErrorMessage(INVALID_COMM_ERROR_MSG21);
            inRetVal = VS_ERR;
        }
    }

    return (inRetVal);
}

#undef VSFIELDS_C

